#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cassert>
#include <sys/wait.h>
using namespace std;


void PrintSig(sigset_t &pending)
{
    std::cout << "Pending bitmap: ";
    for (int signo = 31; signo > 0; signo--)
    {
        if (sigismember(&pending, signo))
        {
            std::cout << "1";
        }
        else
        {
            std::cout << "0";
        }
    }
    std::cout << std::endl;
}

void handler(int signo)
{
    sigset_t pending;
    sigemptyset(&pending);
    int n = sigpending(&pending);// 我正在处理2号信号
    assert(n == 0);

    // 3. 打印pending位图中的收到的信号
    cout << "递达中....: ";
    PrintSig(pending);// 0 : 递达之前, pending 2号已经被清0.  1 : pending被清0 是递达之后
    cout << signo << " 号信号被递达处理..." << endl;
}



int main()
{
    // 对2号信号进行自定义捕捉 --- 不让进程因为2号信号而终止
    signal(2, handler);

    //1. 屏蔽2号信号
    sigset_t block, oblock;
    sigemptyset(&block);
    sigemptyset(&oblock);
    int n = sigaddset(&block, 2);// SIGINT -- 根本没有设置进当前进程的 PCB block位图里
    assert(n == 0);

    //1.1 开始屏蔽 2 号信号, 其实就是设置进入内核
    sigprocmask(SIG_SETMASK, &block, &oblock);
    cout << "block 2 signal success" << endl;
    cout << "pid : " << getpid() << endl;

    int cnt = 0;
    while (true)
    {
       
        // 2 获取pending 位图
        sigset_t pending;
        sigemptyset(&pending);
        n = sigpending(&pending);
        assert(n == 0);

        // 3. 打印pending位图中的收到的信号
        PrintSig(pending);
        cnt++;

        // 4. 解除2号信号的屏蔽
        if(cnt == 20)
        {
            cout << "解除对 2 号信号的屏蔽" << endl;
            n = sigprocmask(SIG_UNBLOCK, &block, &oblock);//2号信号会立即递达, 默认处理动作是终止进程
            assert(n == 0);
        }

        sleep(1);
    }

    return 0;
}


// int main()
// {
//     pid_t id = fork();
//     if(id == 0)
//     {
//         sleep(2);
//         int a = 10;
//         a /= 0; // 故意异常，收到SIGFPE-> core
//         exit(0);
//     }

//     // father
//     int status = 0;
//     pid_t rid = waitpid(id, &status, 0);
//     if(rid > 0)
//     {
//         std::cout << "exit code: " << ((status>>8) & 0xFF) << std::endl; // 没有意义
//         std::cout << "exit signal: " << (status & 0x7F) << std::endl;
//         std::cout << "core dump: " << ((status>>7) & 0x1) << std::endl;
//     }
//     return 0;
// }


// int main()
// {
//     int a = 10;
//     a /= 0; // SIGFPE -> Core

//     while (true) sleep(1);
//     return 0;
// }










